//
// RTP数据流发送
// Created by kenny on 25-11-10.
//
#include "../mcp_logger.h"
#include <stdint.h>
#include "mcp_media.h"
#include "../mcp_udp.h"
#include "../media/media_format.h"
#include "../rtp/h264.h"
#include "../rtp/h265.h"
#include "../bm/sys_inc.h"
#include "../rtp/rtp.h"

#define RTP_VERSION         2
#define  LIVE_AUDIO_TYPE    1 // 定义实时流中的音频格式0-PCMA 1-G711A

// rtp_ps_video_tx -> rtp_video_build2 -> rtp_udp_tx
int rtp_tcp_tx(SUA * p_sua, UA_MEDIA * p_media, void * p_data, int len) {
	return 0;
}
/**
 * UDP 发送RTP 数据流
 * Send rtp data by UDP socket
 * @param p_sua rtsp user agent
 * @param p_media whether video rtp data
 * @param p_rtp_data rtp data
 * @param len rtp data len
 * @return -1 on error, or the data length has been sent
 */
int rtp_udp_tx(SUA * p_sua, UA_MEDIA * p_media, uint8_t * p_rtp_data, int len)
{
	LOG_DEBUG("rtp_udp_tx p_media->remote_port[%d],p_media->local_port=[%d]\n",p_media->remote_port,p_media->local_port);

	int slen;
	int fd = p_media->ua_m_fd;
	if (fd <= 0)
	{
		LOG_DEBUG("rtp_udp_tx--------- fd <= 0  err\n");
		return -1;
	}
	//对方远程端口
	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(p_sua->mcp_udp.server_port); // 服务器收流端口
	server_addr.sin_addr.s_addr = inet_addr(p_sua->mcp_udp.server_ip); // 服务器IP


	LOG_DEBUG("rtp_udp_tx---------  p_media->remote_port[%d],p_media->local_port=[%d]\n",p_media->remote_port,p_media->local_port);
	if (p_sua->uaf_rtp_mux)
    {
    	fd = p_media->mux_fd;
    }

//绑定本地端口
	struct sockaddr localaddr;
	struct sockaddr_in* addr_v4;
	int addr_len = sizeof(localaddr);

	//获取local ip and port
	memset(&localaddr,0,sizeof(localaddr));
	if (0 == getsockname(fd, &localaddr, &addr_len))
	{
		if (localaddr.sa_family == AF_INET)
		{
			int localSourcePort = ntohs(((struct sockaddr_in*)&localaddr)->sin_port);
			LOG_DEBUG("rtp localSourcePort=[%d]\n",localSourcePort);
		}
	}

		/*int kk;
		char szTmp[4*1024]="";
		//DbugLog("send:");
		for(kk=0;kk<len&&kk<50;kk++)
		{
			//DbugLog("0x%02X ",((const char *)p_data+offset)[kk]);
			LOG_DEBUG(szTmp+kk*2,"%02X ",((const char *)p_rtp_data)[kk]);
		}
		LOG_DEBUG("rtp_udp_tx---------send[%d]:%s ----\n",len,szTmp);*/

	slen = sendto(fd, (char *)p_rtp_data, len, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));

	if (slen != len)
	{
		LOG_INFO("rtp_udp_tx --remote_port[%d],local_port=[%d]----slen = %d != len = %d  ERR\r\n",p_media->remote_port,p_media->local_port,slen, len);
	}
	LOG_INFO("rtp_udp_tx ----remote_port[%d],local_port=[%d]----slen = %d, len = %d\r\n",p_media->remote_port,p_media->local_port, slen, len);
	LOG_DEBUG("rtp_udp_tx ----remote_port[%d],local_port=[%d]----slen = %d, len = %d\r\n",p_media->remote_port,p_media->local_port, slen, len);
	return slen;
}

int rtp_video_build2(SUA * p_sua, uint8_t * p_data, int len, int mbit,int nType)//实时音视频
{
	int slen = 0;
	int offset = 0;
	uint8_t buff[40];
	uint8_t * p_hdr_ptr;
	// 是否是TCP 推流
	if (p_sua->uaf_v_tcp_rtp)
	{
		//将16位短整型（2字节）从主机字节序转换为网络字节序
		*(uint16_t *)(buff+offset) = htons(12 + len);  //
		LOG_DEBUG("rtp_video_build2 uaf_v_tcp_rtp>>>>>>>offset=%d,[%d]",offset,*(buff+offset));
		offset += 2;
	}
	LOG_DEBUG("rtp_video_build2 rtpmutx??");
	if (p_sua->uaf_rtp_mux)
	{
		// 将32位长整型（4字节）从主机字节序转换为网络字节序
	    *(uint32_t *)(buff+offset) = htonl(p_sua->video_rtp_media.mux_id);
		LOG_DEBUG("rtp_video_build2 uaf_rtp_mux>>>>>offset=%d,[%d]",offset,*(buff+offset));
		offset += 4;
	}

	*(buff+offset) =  (RTP_VERSION << 6);  //  V=10,P=0,X=0, CC=0000  //版本号，此版本固定为2 V=2 P=0 //  0x80=[‭1000 0000‬‬]
	LOG_DEBUG("rtp_video_build2[%s,%d]offset=%d, ",__FILE__,__LINE__,offset);
	offset++;
    //log_print(LOG_DBG,"rtp_video_build2----------v pt:%d a pt:%d\n",p_sua->v_rtp_info.rtp_pt,p_sua->a_rtp_info.rtp_pt);
	if(nType>0)
		*(buff+offset) = (p_sua->v_rtp_info.rtp_pt) | ((mbit & 0x01) << 7); // M=1,PT=111 1111 // 0x60=[0110 0000‬]
    else{
    	if(LIVE_AUDIO_TYPE)
			*(buff+offset) = (p_sua->a_rtp_info.rtp_pt) | ((mbit & 0x01) << 7);//20110122 改RTP头负载p_sua->a_rtp_info.rtp_pt  8-pcmA 37AAC 96:ps
		else
			*(buff+offset) = (8) | ((mbit & 0x01) << 7);
	}
	offset++;
	//*(uint16*)(buff+offset) = htons((uint16)(p_sua->a_rtp_info.rtp_cnt)); //sequence number=1111 1111, 1111 1111   //0x0,0x11 =[‭00000000,‭00010001‬‬‬]
	*(uint16_t*)(buff+offset) = htons((uint16_t)(p_sua->v_rtp_info.rtp_cnt));
	//DbugLog("rtp_video_build2[%s,%d]offset=%d,[%d]",__FILE__,__LINE__,offset,*(buff+offset));
	offset += 2;
	*(uint32_t*)(buff+offset) = htonl(p_sua->v_rtp_info.rtp_ts); //timestamp = 1111 1111, 1111 1111,1111 1111, 1111 1111
															 // 0xf4,0x17,0x55,0x0 =[‭1111 0100 ,0001 0111,0101 0101, 0000 0000‬‬‬]
	LOG_DEBUG("rtp_video_build2[%s,%d]offset=%d",__FILE__,__LINE__,offset);
	offset += 4;
	LOG_DEBUG("rtp_video_build2[%s,%d]offset=%d",__FILE__,__LINE__,offset);
	*(uint32_t*)(buff+offset) = htonl(p_sua->v_rtp_info.rtp_ssrc); //SSRC==  1111 1111, 1111 1111,1111 1111, 1111 1111

	LOG_DEBUG("rtp_video_build2流的rtp_ssrc=%d\n",p_sua->v_rtp_info.rtp_ssrc );															//0x0c,0xb9,0xf2,0x3f,=[0000 ‭1100, 1011 1001, 1111 0010,0011 1111‬‬]
	//DbugLog("rtp_video_build2[%s,%d]offset=%d,[%d]",__FILE__,__LINE__,offset,*(buff+offset));
	offset += 4;

	p_hdr_ptr = p_data - offset;
	memcpy(p_hdr_ptr, buff, offset); //rtp头拷贝到buff
	LOG_DEBUG("rtp_video_build2=====RTP=offset+len=[%d]",offset+len);
	// 0x00 0x00 0x00 0x00 0x5D 0x35 0x32 0x7F 0x09
	if (p_sua->uaf_v_tcp_rtp)
	{
		//DbugLog("[%s:%d]TCP 发送\n",__FILE__,__LINE__);
		LOG_DEBUG("rtp_video_build2----------TCP 发送-fd:%d SSRC:%d-len:%d index:%d ts:[[%u]] back:%d\n",
			p_sua->video_rtp_media.ua_m_fd,p_sua->v_rtp_info.rtp_ssrc ,offset+len,p_sua->v_rtp_info.rtp_cnt,
			p_sua->v_rtp_info.rtp_ts,p_sua->uaf_playback);
		slen = rtp_tcp_tx(p_sua, &p_sua->video_rtp_media, p_hdr_ptr, offset+len);
		if (slen != offset+len)
		{
			return -1;
		}
	}
	else
	{
		//DbugLog("rtp_video_build2 [%s:%d]UDP 发送\n",__FILE__,__LINE__);
		LOG_DEBUG("rtp_video_build2----------UDP 发送-fd:%d  SSRC:%d-len:%d index:%d\n",p_sua->video_rtp_media.ua_m_fd,p_sua->v_rtp_info.rtp_ssrc ,offset+len,p_sua->v_rtp_info.rtp_cnt);
		slen = rtp_udp_tx(p_sua, &p_sua->video_rtp_media, p_hdr_ptr, offset+len);
		if (slen != offset+len)
		{
			return -1;
		}
	}
	p_sua->v_rtp_info.rtp_cnt++;   //20220122 dcw 实时音视频是否用同一个序列号

	return slen;
}

int rtp_ps_video_tx(SUA * p_sua, uint8_t * p_data, int len, uint32_t ts)
{
	LOG_DEBUG("rtp_ps_video_tx \n");

	int ps_cnt = 0;
	int i_flag = 0;
	int ps_hdr_len, remain_len = len, tx_remain, offset, tx_len;
	uint8_t nalu_t;
	uint8_t tmp_buf[512];
	uint32_t used_size = 0;
	int vtype = 0x1b;
	int atype = 0x90;

    if (VIDEO_CODEC_H264 == p_sua->media_info.vcodec)
    {
        vtype = 0x1b;

        nalu_t = p_data[4] & 0x1F;
        if (nalu_t == H264_NAL_SPS || nalu_t == H264_NAL_PPS || nalu_t == H264_NAL_IDR || nalu_t == H264_NAL_SEI)
    	{
    		i_flag = 1;
    	}
    }
    else if (VIDEO_CODEC_H265 == p_sua->media_info.vcodec)
    {
        vtype = 0x24;

        nalu_t = (p_data[4] & 0x7E) >> 1;
        if ((nalu_t >= 16 && nalu_t <= 21) || nalu_t == HEVC_NAL_VPS || nalu_t == HEVC_NAL_SPS || nalu_t == HEVC_NAL_PPS)
    	{
    		i_flag = 1;
    	}
    }
    else if (VIDEO_CODEC_MP4 == p_sua->media_info.vcodec)
    {
        vtype = 0x10;
        int pos = 0;
        while (pos < len - 5)
        {
            if (p_data[pos] == 0 && p_data[pos+1] == 0 && p_data[pos+2] == 1)
            {
                if (p_data[pos+3] == 0xb6)
                {
                    if ((p_data[4] & 0xC0) == 0)
                    {
                        i_flag = 1;
                    }

                    break;
                }
                else
                {
                    pos += 4;
                }
            }
            else
            {
                pos++;
            }
        }
    }
    if (AUDIO_CODEC_G711A == p_sua->media_info.acodec)
    {
        atype = 0x90;
    }
	if (AUDIO_CODEC_G711U == p_sua->media_info.acodec)
	{
		atype = 0x91;
	}
    else if (AUDIO_CODEC_G722 == p_sua->media_info.acodec)
    {
        atype = 0x92;
    }
	else if (AUDIO_CODEC_AAC == p_sua->media_info.acodec)
	{
		atype = 0x0F;
	}
	else
	{
		atype = 0x90;
	}
	sys_os_mutex_enter(p_sua->pstxi_mutex);
	// PS 初始化信息
	ps_init_info(&p_sua->pstxi, vtype, atype);

	while (remain_len > 0)
	{
		int pkt_type = (i_flag == 1) ? 3 : 1;
		if (ps_cnt > 0)
		{
			pkt_type = 4;
		}

		ps_hdr_len = ps_make_header(&p_sua->pstxi, tmp_buf, remain_len, ts, pkt_type, &used_size);

		tx_remain = used_size + ps_hdr_len;	// 本次组PS包的总长度
		offset = len - remain_len - ps_hdr_len;
		memcpy(p_data + offset, tmp_buf, ps_hdr_len);

		remain_len -= used_size;
		while (tx_remain > 0)
		{
			tx_len = (tx_remain > H264_RTP_MAX_LEN) ? H264_RTP_MAX_LEN : tx_remain;
			p_sua->v_rtp_info.rtp_ts = ts;
			tx_remain -= tx_len;
			int mark = (tx_remain > 0 || remain_len > 0) ? 0 : 1;
			LOG_DEBUG("rtp_video_build$$$$$$$[%s:%d=======]\n",__FILE__,__LINE__);
			LOG_DEBUG("rtp_video_build  len:%d offset:%d tx_remain:%d tx_len:%d=====\n",len,offset,tx_remain,tx_len);
			int ret = rtp_video_build2(p_sua, p_data + offset, tx_len, mark,1);
			if (ret < 0)
			{
			    sys_os_mutex_leave(p_sua->pstxi_mutex);
				return -1;
			}
			p_sua->video_rtp_media.last_pkt_time = sys_os_get_uptime();
			offset += tx_len;
		}
		ps_cnt++;
		p_sua->video_rtp_media.tx_pkt_cnt++;
	}
    sys_os_mutex_leave(p_sua->pstxi_mutex);

	return 0;
}